'''
Created on 21/03/2012

@author: laarguelless
'''


from tkinter import ttk, Tk, Canvas, BooleanVar, N, E, S, W, StringVar, IntVar
from turtle import TurtleScreen, RawTurtle
from Grammar import GrammarControl


class PrincipalWindow:
    def __init__(self):
        
        self.root = Tk()
        self.root.title('L-system')
        
        self.content = ttk.Frame(self.root, padding=(3, 3, 12, 12))
        self.canvas = Canvas(self.content, borderwidth=5, relief="sunken", width=800, height=600)
        self.contentEntry = ttk.Frame(self.content, padding=(3, 3, 12, 12))
        
        self.screen = TurtleScreen(self.canvas)
        self.turtle = RawTurtle(self.screen)        
        self.screen.mode("logo")
        self.turtle.hideturtle()
        
        
        self.axiom = StringVar()        
        self.axiomMssg = StringVar()
        self.rules = StringVar()
        self.rulesMssg = StringVar()
        self.iterations = IntVar()
        self.angle = StringVar()
        self.angleMssg = StringVar()
        self.random = BooleanVar()
        self.random.set(False)
        self.color = BooleanVar()
        self.random.set(False)
        self.iterationsMssg = StringVar()
        self.initialStep = IntVar()
        self.initialStepMssg = StringVar()
        self.reductionFactor = IntVar()
        self.initx = StringVar()
        self.initxMssg = StringVar()
        self.inity = StringVar()
        self.inityMssg = StringVar()
        
        
        self.iterations.set(0)
        self.angle.set('90')
        self.reductionFactor.set(2)
        self.initialStep.set(100)
        self.initx.set('0.0')
        self.inity.set('-200.0')
        
        self.axiomlbl = ttk.Label(self.contentEntry, text="Start")
        self.axiomEntry = ttk.Entry(self.contentEntry, textvariable=self.axiom)
        self.axiomMssglbl = ttk.Label(self.contentEntry, textvariable=self.axiomMssg, foreground="red")
        
        self.ruleslbl = ttk.Label(self.contentEntry, text="Rules")
        self.rulesEntry = ttk.Entry(self.contentEntry, textvariable=self.rules)
        self.rulesMssglbl = ttk.Label(self.contentEntry, textvariable = self.rulesMssg, foreground="red")
        
        self.iterationlbl = ttk.Label(self.contentEntry, text="Number of iterations")
        self.iterationsEntry = ttk.Entry(self.contentEntry, textvariable=self.iterations)
        self.iterationsMssglbl = ttk.Label(self.contentEntry, textvariable=self.iterationsMssg, foreground ="red")
       
        self.anglelbl = ttk.Label(self.contentEntry,text="Angle")
        self.angleEntry = ttk.Entry(self.contentEntry,textvariable=self.angle)
        self.angleMssglbl = ttk.Label(self.contentEntry,textvariable=self.angleMssg, foreground="red")
        
        self.randomCB = ttk.Checkbutton(self.contentEntry, text="random behaviour", variable=self.random, onvalue=True)
        self.colorCB = ttk.Checkbutton(self.contentEntry, text="Color Mode", variable=self.color, onvalue=True)
        
        self.generateButton = ttk.Button(self.content, text="Generate", command=self.Generate)
        self.quitButton = ttk.Button(self.content, text="Quit", command=quit)
        
        self.initialSteplbl = ttk.Label(self.contentEntry,text="Initial Step")
        self.initialStepEntry = ttk.Entry(self.contentEntry,textvariable=self.initialStep)
        self.initialStepMssglbl = ttk.Label(self.contentEntry,textvariable=self.initialStepMssg, foreground="red")
        
        self.initialXlbl = ttk.Label(self.contentEntry,text="Initial x pos")
        self.initialXEntry = ttk.Entry(self.contentEntry,textvariable=self.initx)
        self.initialXMssglbl = ttk.Label(self.contentEntry,textvariable=self.initxMssg, foreground="red")
        
        self.initialYlbl = ttk.Label(self.contentEntry,text="Initial y pos")
        self.initialYEntry = ttk.Entry(self.contentEntry,textvariable=self.inity)
        self.initialYMssglbl = ttk.Label(self.contentEntry,textvariable=self.inityMssg, foreground="red")
        
        self.content.grid(column=0, row=0, sticky=(N, S, E, W))
        self.canvas.grid(column=0, row=0, columnspan=3, rowspan=2, sticky=(N, S, E, W))
        self.contentEntry.grid(column=3, row=0, sticky=(N, S, E, W))
       
        self.axiomlbl.grid(column=1, row=0, columnspan=2, sticky=(N, W), padx=5)
        self.axiomEntry.grid(column=1, row=1, columnspan=2, sticky=(N, E, W), pady=5, padx=5)
        self.axiomMssglbl.grid(column=1, row=2,columnspan=2,sticky=(N,W),pady=5,padx=5)
        
        self.ruleslbl.grid(column=1,row=3,columnspan=2,sticky = (N,W),pady=5,padx=5)
        self.rulesEntry.grid(column=1,row=4,columnspan=2,sticky = (N,W,E),pady=5,padx=5)
        self.rulesMssglbl.grid(column=1,row=5,columnspan=2,sticky=(N,W),pady=5,padx=5)
        
        self.iterationlbl.grid(column=1, row=6, columnspan=2, sticky=(N, W), pady=5, padx=5)
        self.iterationsEntry.grid(column=1, row=7, columnspan=2, sticky=(N, E, W), pady=5, padx=5)
        self.iterationsMssglbl.grid(column=1,row=8, columnspan=2, sticky=(N,W),pady=5,padx=5)
        
        self.anglelbl.grid(column=1, row=9, columnspan=2, sticky=(N, W), pady=5, padx=5)
        self.angleEntry.grid(column=1, row=10, columnspan=2, sticky=(N, E, W), pady=5, padx=5)
        self.angleMssglbl.grid(column=1,row=11, columnspan=2, sticky=(N,W),pady=5,padx=5)
        
        self.randomCB.grid(column=1, row=12, columnspan=2, sticky=(N,W),pady=5,padx=5)
        self.colorCB.grid(column=1, row=13, columnspan=2, sticky=(N,W),pady=5,padx=5)
        self.generateButton.grid(column=3, row=3)
        self.quitButton.grid(column=4, row=3)
        
        self.initialSteplbl.grid(column=1, row=14, columnspan=2, sticky=(N, W), pady=5, padx=5)
        self.initialStepEntry.grid(column=1, row=15, columnspan=2, sticky=(N, E, W), pady=5, padx=5)
        self.initialStepMssglbl.grid(column=1,row=16, columnspan=2, sticky=(N,W),pady=5,padx=5)
        
        self.initialXlbl.grid(column=1, row=17, columnspan=2, sticky=(N, W), pady=5, padx=5)
        self.initialXEntry.grid(column=1, row=18, columnspan=2, sticky=(N, E, W), pady=5, padx=5)
        self.initialXMssglbl.grid(column=1,row=19, columnspan=2, sticky=(N,W),pady=5,padx=5)
        
        self.initialYlbl.grid(column=1, row=20, columnspan=2, sticky=(N, W), pady=5, padx=5)
        self.initialYEntry.grid(column=1, row=21, columnspan=2, sticky=(N, E, W), pady=5, padx=5)
        self.initialYMssglbl.grid(column=1,row=22, columnspan=2, sticky=(N,W),pady=5,padx=5)
        
        self.root.columnconfigure(0, weight=1)
        self.root.rowconfigure(0, weight=1)
        self.content.columnconfigure(0, weight=3)
        self.content.columnconfigure(1, weight=3)
        self.content.columnconfigure(2, weight=3)
        self.content.columnconfigure(3, weight=1)
        self.content.columnconfigure(4, weight=1)
        self.content.rowconfigure(1, weight=1)       
        
        self.axiomEntry.focus()
        self.root.mainloop()
    
    def Generate(self):        
       
        #Clean Mssgs
        if(self.verifyPosx() and self.verifyPosy()):
            self.clean()
            self.iterationsMssg.set("")
            self.axiomMssg.set("")
            self.rulesMssg.set("")
            self.initxMssg.set("")
            self.inityMssg.set("")
            self.angleMssg.set("")
            self.initialStepMssg.set("")
            #clean spacies
            self.axiom.set(self.axiom.get().replace(" ",""))
            self.rules.set(self.rules.get().replace(" ", ""))
               
            if(self.verifyIterations() and self.verifyAngle() and self.verifyInitialStep()):
                grammarControl = GrammarControl(self.axiom.get(),self.rules.get(), self.turtle,self.screen,float(self.angle.get()), self.iterations.get(), self.random.get(), self.initialStep.get(), self.reductionFactor.get(), self.color.get())                
                if(self.verifyAxiom(grammarControl.verifyAxiom()) and self.verifyRules(grammarControl.verifyRule())):
                    grammarControl.drawLSystem()
            
    
    def verifyAxiom(self,boolean):        
        if(not boolean):
            self.axiomMssg.set("Incorrect or empty Axiom")
            self.axiomEntry.focus()
        return boolean
    
    def verifyRules(self, boolean):
        if(not boolean):
            self.rulesMssg.set("Incorrect or empty rule")
            self.rulesEntry.focus()
        return boolean
            
        
    def verifyIterations(self):
        try:
            self.iterations.set(int(self.iterations.get()))
            if(self.iterations.get() >= 0):                           
                return True
            else:
                self.iterationsMssg.set("Iterations must be greater or equal than zero")
        except ValueError:
            self.iterationsMssg.set("Iterations must be a integer number")
            return False
    
    def verifyAngle(self):
        try:
            self.angle.set(float(self.angle.get()))
            if(self.angle.get() == 0.0):
                self.angleMssg.set("The angle must be different of zero")
                return False
            return True
        except ValueError:
                self.angleMssg.set("The angle must be a number")
                return False
    
    def verifyInitialStep(self):
        try:
            self.initialStep.set(int(self.initialStep.get()))
            if(self.initialStep.get() > 5):                           
                return True
            else:
                self.initialStepMssg.set("Initial Step must be greater or equal than five")
        except ValueError:
            self.initialStepMssg.set("Initial Step must be a integer number")
            return False
        
    def verifyPosx(self):
        try:
            self.initx.set(float(self.initx.get()))
            if(float(self.initx.get()) > 400 or float(self.initx.get()) < -400):
                self.initxMssg.set("The point is out of the screen")
                return False
            return True
        except ValueError:
                self.initxMssg.set("The posx must be a number")
                return False
            
    def verifyPosy(self):
        try:
            self.inity.set(float(self.inity.get()))
            if(float(self.inity.get()) > 300 or float(self.inity.get()) < -300):
                self.inityMssg.set("The point is out of the screen")
                return False
            return True
        except ValueError:
                self.inityMssg.set("The posy must be a number")
                return False
            
    def clean(self):        
        self.turtle.clear()
        self.turtle.up()
        self.turtle.setpos(float(self.initx.get()),float(self.inity.get()))
        self.turtle.seth(0.0)
        self.turtle.down()
        self.turtle.speed("fastest")
       
if __name__ == "__main__":
    window = PrincipalWindow()
